package com.poseidon.prototype;

import com.jmex.physics.CollisionGroup;

/**
 * all the variable are string because they have the unit of conversion to
 * example:
 * robotLenght = xx mm
 *      xx cm
 *      xx m
 *
 * Use String.split(" ") for take the two value!
 *
 * About the conversion I decided to work in only one way:
 * 1 knots = 0,51 m/s = 0.51 v (velocity)
 * density =
 * 1 kgf = 9.80665 N (newtons)
 * 1 N = kg m/s^2
 * 1 kg
 * Meters - Newton - Velocity - KGram
 *
 * PhysicsSpace p;
 * p.setDirectionalGravity(new Vector3f(0, -9.81f, 0));
 *
 */
public class Physics {


 private String gravityValue;
 private String friction;
 private String robotMaxSpeed;
 private String robotMass;
 private String robotLenght;
 private String robotHeight;
 private String robotWidth;
 private String robotPayload;
 private String robotThrustForwardForce;
 private String robotThrustLateralForce;
 private String robotThrustVerticalForce;
 private String waterDensity;
 private String maximumWorkingDepth;
 private String frictionAreaReference;
 private String frictionDragCoefficient;

 private double robotVolume;
 private double robotDensity;

 private double liftPushUp;
 private double gravityPushDown;
 private double impulsePush;
 private double frictionPush;


 //private String




 public boolean isrobotMass(){
  if (robotMass ==null)
   return false;
  return true;
 }
 public boolean isGravity(){
  if (gravityValue == null)
   return false;
  return true;
 }
 public boolean isRobotMaxSpeed(){
  if (robotMaxSpeed == null)
   return false;
  return true;
 }
 public boolean isFriction(){
  if (friction == null)
   return false;
  return true;
 }

 /**
  * Michel Uncini 18/12/2009
     *
     * A fluid flowing past the surface of a body exerts a force on it.
     * Lift is defined to be the component of
  * this force that is perpendicular to the oncoming flow direction.
     *
     * @param   .
     * @return null
     */

 public void calcolateLiftPushUp(){
  String[] strWaterDensity = extractValue(this.waterDensity);
  String[] strGravity = extractValue(this.gravityValue);

  double unconvertValue = Double.parseDouble(strWaterDensity[0]);
  String unit = strWaterDensity[1];
  double waterDensityValue = convertUnitStandard(unconvertValue, unit);

  unconvertValue = Double.parseDouble(strGravity[0]);
  unit = strGravity[1];
  double gravityValue = convertUnitStandard(unconvertValue, unit);


  this.liftPushUp = waterDensityValue * gravityValue * this.robotVolume;
 }

 /**
  * Michel Uncini 18/12/2009
     *
     * when a force is applied to a rigid body, it changes the momentum of that body.
     * A small force applied for a long time can produce the same momentum change as a large
     * force applied briefly, because it is the prodect of the force and the time for which it is
     * applied that is important. Also, you can define the Impluse like this:
  *
     *
     * @param acc  .
     * @return null
     */
 public void calcolateImpulse(double acc){
  String[] strMass = extractValue(this.robotMass);

  double unconvertValue = Double.parseDouble(strMass[0]);
  String unit = strMass[1];
  double massaValue = convertUnitStandard(unconvertValue, unit);


  this.setImpulsePush(massaValue * acc);
 }

 public void calcolateGravityPushDown(){
  String[] strGravity = extractValue(this.gravityValue);

  double unconvertValue = Double.parseDouble(strGravity[0]);
  String unit = strGravity[1];
  double gravityValue = convertUnitStandard(unconvertValue, unit);


  this.setGravityPushDown(gravityValue * this.robotDensity * this.robotVolume);
 }




 /**
  * Michel Uncini 18/12/2009
     * Acceleration = Force / Mass
     *
     * you have to specify where the acceleration rises
     *
     * @param thrust where the forces is rise.
     * @return acceleration
     */
 public double calcolateAcceleration(int thrust){
  double acc = -1;


  String[] strRobotThF = extractValue(this.robotThrustForwardForce);
  String[] strRobotThL = extractValue(this.robotThrustLateralForce);
  String[] strRobotThV = extractValue(this.robotThrustVerticalForce);
  String[] strMass = extractValue(this.robotMass);

  double unconvertValue = Double.parseDouble(strRobotThF[0]);
  String unit = strRobotThF[1];
  double thF = convertUnitStandard(unconvertValue, unit);

  unconvertValue = Double.parseDouble(strRobotThL[0]);
  unit = strRobotThL[1];
  double thL = convertUnitStandard(unconvertValue, unit);

  unconvertValue = Double.parseDouble(strRobotThV[0]);
  unit = strRobotThV[1];
  double thV = convertUnitStandard(unconvertValue, unit);

  unconvertValue = Double.parseDouble(strMass[0]);
  unit = strMass[1];
  double mass = convertUnitStandard(unconvertValue, unit);

  switch (thrust) {
  case 1:
   acc = thF / mass;
   break;
  case 2:
   acc = thL / mass;
   break;
  case 3:
   acc = thV / mass;
   break;
  default:
   break;
  }

  return acc;

 }
 /**
  * Michel Uncini 18/12/2009
     *
     *The friction calculates the force experienced by an object moving through a
     *fluid at relatively large velocity.
  *
     *
     * @param velocity .
     * @return null
     */
 public void calcolateFriction(double velocity){
  String[] strWaterDensity = extractValue(this.waterDensity);
  String[] strDrag = extractValue(this.frictionDragCoefficient);
  String[] strArea = extractValue(this.frictionAreaReference);
  double unitVectorDirectorVelocity = 1;

  double unconvertValue = Double.parseDouble(strWaterDensity[0]);
  String unit = strWaterDensity[1];
  double waterDensityValue = convertUnitStandard(unconvertValue, unit);

  unconvertValue = Double.parseDouble(strDrag[0]);
  unit = strDrag[1];
  double dragValue = convertUnitStandard(unconvertValue, unit);

  unconvertValue = Double.parseDouble(strArea[0]);
  unit = strArea[1];
  double areaValue = convertUnitStandard(unconvertValue, unit);


  this.setFrictionPush(-0.5 * waterDensityValue * dragValue * areaValue * Math.pow(velocity,2) * unitVectorDirectorVelocity);
 }


 /**
  * Michel Uncini 18/12/2009
     *
     ** all the variable are string because they have the unit of conversion to
     * example:
     * robotLenght = xx mm
     *      xx cm
     *      xx m
  *
     *
     * @param str
     * @return String[]
     */
 public String[] extractValue(String str){
  String[] strTry = str.split(" ");
  return strTry;
 }
 /**
  * Michel Uncini 18/12/2009
     *
     *Convetr to standard unit
  *if you don't have to convert just return the same value
     *
     * @param velocity .
     * @return null
     */
 public double convertUnitStandard(double value,String unit){
  double newValue = value;

  if (unit.equals("mm")){ //convert in meters M
   newValue = value / 1000;
  }else if (unit.equals("cm")){ //convert in meters M
   newValue = value / 100;
  }else if (unit.equals("dm")){ //convert in meters M
   newValue = value / 10;
  }else if (unit.equals("kgf")){ //convert in 9.80665 N (Newton)
   newValue = value * 9.80665;
  }else if (unit.equals("knots")){ //1 knots = 0,51 m/s = 0.51 v (velocity)
   newValue = value * 0.51;
  }else if (unit.equals("m^2")){

  }else if (unit.equals("x")){

  }else if (unit.equals("m/s^2")){

  }else if (unit.equals("kg/m^3")){

  }

  return newValue;

 }

 public void calcolateRobotVolume(){
  String[] strW = extractValue(this.robotWidth);
  String[] strH = extractValue(this.robotHeight);
  String[] strL = extractValue(this.robotLenght);

  double unconvertValue = Double.parseDouble(strW[0]);
  String unit = strW[1];
  double wValue = convertUnitStandard(unconvertValue, unit);

  unconvertValue = Double.parseDouble(strH[0]);
  unit = strH[1];
  double hValue = convertUnitStandard(unconvertValue, unit);

  unconvertValue = Double.parseDouble(strL[0]);
  unit = strL[1];
  double lValue = convertUnitStandard(unconvertValue, unit);


  this.robotVolume = wValue * hValue * lValue ;

 }
 public void calcolateRobotDensity(){
  String[] strMassa = extractValue(this.robotMass);

  double unconvertValue = Double.parseDouble(strMassa[0]);
  String unit = strMassa[1];
  double massaValue = convertUnitStandard(unconvertValue, unit);

  this.robotDensity = massaValue / this.robotVolume;
 }




 public void setRobotMass(String robotMass) {
  this.robotMass = robotMass;
 }

 public void setGravityValue(String gravityValue) {

  this.gravityValue = gravityValue;
 }

 public String getRobotMass() {
  return robotMass;
 }
 public String getGravityValue() {
  return gravityValue;
 }

 public String toString() {
          return "Gravity = " + this.gravityValue
             + "\nrobotMass    = " + this.robotMass
             + "\nfriction    = " + this.friction
             + "\nrobotMaxSpeed    = " + this.robotMaxSpeed
             + "\robotHeight    = " + this.robotHeight
             + "\nRobotLenght    = " + this.robotLenght
             + "\nRobotPayload    = " + this.robotPayload
             + "\nrobotThrustForwardForce    = " + this.robotThrustForwardForce
             + "\nrobotThrustLateralForce    = " + this.robotThrustLateralForce
             + "\nrobotThrustVerticalForce    = " + this.robotThrustVerticalForce
             + "\nrobotWidth    = " + this.robotWidth
             + "\nwaterDensity    = " + this.waterDensity
             + "\nmaximumWorkingDepth    = " + this.maximumWorkingDepth
             + "\nfrictionAreaReference    = " + this.frictionAreaReference
             + "\nfrictionDragCoefficient    = " + this.frictionDragCoefficient
             + "\n"
             + "\nrobotVolume    = " + this.robotVolume + " m^3"
             + "\nrobotDensity    = " + this.robotDensity+ " KG/m^3"
             + "\nliftPushUp    = " + this.liftPushUp+ " N"
             + "\ngravityPushDown    = " + this.gravityPushDown+ " N"
             + "\nimpulsePush    = " + this.impulsePush+ " N"
             + "\nfrictionPush    = " + this.frictionPush+ " N";
 }
 public void setFriction(String friction) {
  this.friction = friction;
 }
 public String getFriction() {
  return friction;
 }
 public void setRobotMaxSpeed(String robotMaxSpeed) {
  this.robotMaxSpeed = robotMaxSpeed;
 }
 public String getRobotMaxSpeed() {
  return robotMaxSpeed;
 }
 public void setRobotLenght(String robotLenght) {
  this.robotLenght = robotLenght;
 }
 public String getRobotLenght() {
  return robotLenght;
 }
 public void setRobotHeight(String robotHeight) {
  this.robotHeight = robotHeight;
 }
 public String getRobotHeight() {
  return robotHeight;
 }
 public void setRobotWidth(String robotWidth) {
  this.robotWidth = robotWidth;
 }
 public String getRobotWidth() {
  return robotWidth;
 }
 public void setRobotPayload(String robotPayload) {
  this.robotPayload = robotPayload;
 }
 public String getRobotPayload() {
  return robotPayload;
 }
 public void setRobotThrustForwardForce(String robotThrustForwardForce) {
  this.robotThrustForwardForce = robotThrustForwardForce;
 }
 public double getRobotThrustForwardForce() {
    String[] strForward = extractValue(this.robotThrustForwardForce);

    double unconvertValue = Double.parseDouble(strForward[0]);
    String unit = strForward[1];
    double thF = convertUnitStandard(unconvertValue, unit);
    return thF;
}
 public void setRobotThrustLateralForce(String robotThrustLateralForce) {
  this.robotThrustLateralForce = robotThrustLateralForce;
 }
 public double getRobotThrustLateralForce() {
  String[] strLateral = extractValue(this.robotThrustLateralForce);

    double unconvertValue = Double.parseDouble(strLateral[0]);
    String unit = strLateral[1];
    double thF = convertUnitStandard(unconvertValue, unit);
    return thF;
 }
 public void setRobotThrustVerticalForce(String robotThrustVerticalForce) {
  this.robotThrustVerticalForce = robotThrustVerticalForce;
 }
 public double getRobotThrustVerticalForce() {
  String[] strVertical = extractValue(this.robotThrustVerticalForce);

    double unconvertValue = Double.parseDouble(strVertical[0]);
    String unit = strVertical[1];
    double thF = convertUnitStandard(unconvertValue, unit);
    return thF;
 }
 public void setWaterDensity(String waterDensity) {
  this.waterDensity = waterDensity;
 }
 public String getWaterDensity() {
  return waterDensity;
 }
 public void setMaximumWorkingDepth(String maximumWorkingDepth) {
  this.maximumWorkingDepth = maximumWorkingDepth;
 }
 public String getMaximumWorkingDepth() {
  return maximumWorkingDepth;
 }
 public void setRobotVolume(Double robotVolume) {
  this.robotVolume = robotVolume;
 }
 public Double getRobotVolume() {
  return robotVolume;
 }
 public void setRobotDensity(Double robotDensity) {
  this.robotDensity = robotDensity;
 }
 public Double getRobotDensity() {
  return robotDensity;
 }
 public void setLiftPushUp(double liftPushUpft) {
  this.liftPushUp = liftPushUpft;
 }
 public double getLiftPushUp() {
  return liftPushUp;
 }
 public void setFrictionAreaReference(String frictionAreaReference) {
  this.frictionAreaReference = frictionAreaReference;
 }
 public String getFrictionAreaReference() {
  return frictionAreaReference;
 }
 public void setFrictionDragCoefficient(String frictionDragCoefficient) {
  this.frictionDragCoefficient = frictionDragCoefficient;
 }
 public String getFrictionDragCoefficient() {
  return frictionDragCoefficient;
 }
 public void setGravityPushDown(double gravityPushDown) {
  this.gravityPushDown = gravityPushDown;
 }
 public double getGravityPushDown() {
  return gravityPushDown;
 }
 public void setImpulsePush(double impulsePush) {
  this.impulsePush = impulsePush;
 }
 public double getImpulsePush() {
  return impulsePush;
 }
 public void setFrictionPush(double frictionPush) {
  this.frictionPush = frictionPush;
 }
 public double getFrictionPush() {
  return frictionPush;
 }
}